﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Web.Mvc;
using Xenta.Utils;
using Xenta.Attributes;
using Xenta.Web.Controllers;

namespace Xenta.Web.Areas.Publishing.Controllers
{
    [Authenticate, InRole("ADMIN")]
    public sealed class PublicationController : ExtController
    {
        #region GET/POST Actions

        [HttpGet]
        public ActionResult Index()
        {
            return View();
        }

        [HttpGet]
        public ActionResult GoTo(int? id, string code)
        {
            if(!id.HasValue)
            {
                dynamic m = null;
                if(!String.IsNullOrWhiteSpace(code))
                {
                    m = Svc.ProcessOperation("GetPublicationByCode", new
                    {
                        Code = code
                    });
                }
                if(m == null)
                    return HttpNotFound();
                id = JDM.Int32(m.EntityID);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id
            }));
        }

        [HttpGet, RestoreState]
        public ActionResult Create()
        {
            return View();
        }

        [HttpPost, PersistState]
        public ActionResult Create(int authorID, 
            int fileGroupID, 
            string code, 
            string[] flags,
            string publishedOn)
        {
            try
            {
                var m = Svc.ProcessOperation("CreatePublication", new
                {
                    AuthorID = authorID,
                    FileGroupID = fileGroupID,
                    Code = code,
                    Flags = flags.Merge(","),
                    PublishedOn = Svc.DateTime(publishedOn)
                });
                return RedirectToAction(Loc.Act("Edit").Set(new
                {
                    id = JDM.Int32(m.EntityID)
                }));
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Create"));
        }

        [HttpGet, RestoreState]
        public ActionResult Edit(int id)
        {
            var m = Svc.ProcessOperation("GetPublication", new
            {
                EntityID = id,
                Fetch = "Entire"
            }, new
            {
                DisclosureLevel = "Entire"
            });
            if(m == null)
                return HttpNotFound();
            return View(m);
        }

        [HttpPost, PersistState]
        public ActionResult Update(int id, 
            int authorID,
            int fileGroupID, 
            string code,
            string[] flags,
            string publishedOn)
        {
            try
            {
                Svc.ProcessOperation("UpdatePublication", new
                {
                    AuthorID = authorID,
                    EntityID = id,
                    FileGroupID = fileGroupID,
                    Code = code,
                    Flags = flags.Merge(","),
                    PublishedOn = Svc.DateTime(publishedOn)
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }

            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id
            }));
        }

        [HttpGet, PersistState]
        public ActionResult Delete(int id, bool deleteFileGroup)
        {
            try
            {
                Svc.ProcessOperation("DeletePublication", new
                {
                    EntityID = id,
                    DeleteFileGroup = deleteFileGroup
                });
                return RedirectToAction(Loc.Act("Index"));
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id
            }));
        }

        [HttpPost, PersistState, ValidateInput(false)]
        public ActionResult CreateTranslation(int publicationID, 
            int languageID, 
            string title, 
            string description, 
            string text)
        {
            try
            {
                Svc.ProcessOperation("CreatePublicationTranslation", new
                {
                    HolderID = publicationID,
                    LanguageID = languageID,
                    Title = HtmlUtility.StripTags(title),
                    Description = HtmlUtility.StripTags(description),
                    Text = HtmlUtility.Encode(text)
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id = publicationID
            }));
        }

        [HttpPost, PersistState, ValidateInput(false)]
        public ActionResult UpdateTranslation(int id, 
            int publicationID,
            int languageID,
            string title,
            string description,
            string text)
        {
            try
            {
                Svc.ProcessOperation("UpdatePublicationTranslation", new
                {
                    EntityID = id,
                    LanguageID = languageID,
                    Title = HtmlUtility.StripTags(title),
                    Description = HtmlUtility.StripTags(description),
                    Text = HtmlUtility.Encode(text)
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id = publicationID
            }));
        }

        [HttpGet, PersistState]
        public ActionResult DeleteTranslation(int id, int publicationID)
        {
            try
            {
                Svc.ProcessOperation("DeletePublicationTranslation", new
                {
                    EntityID = id
                });
            }
            catch(Exception ex)
            {
                ModelState.AddModelError("API", ex);
            }
            return RedirectToAction(Loc.Act("Edit").Set(new
            {
                id = publicationID
            }));
        }

        #endregion

        #region AJAX Actions

        [HttpPost]
        public ActionResult Grid(int? page, 
            int? rows, 
            string sord, 
            string sidx,
            string searchTerm,
            int? authorID,
            int? tagID,
            string attributeIDs,
            string createdFrom,
            string createdTo,
            string publishedFrom,
            string publishedTo,
            string flagMask)
        {
            page = page.HasValue ? page.Value - 1 : 0;
            rows = rows.HasValue ? rows.Value : 30;
            sord = sord.Equals("desc") ? "Descending" : "Ascending";

            var m = Svc.ProcessOperation("SearchPublications", new 
            {
                Term = new
                {
                    Expression = searchTerm
                },
                AuthorID = authorID,
                TagID = tagID,
                AttributeIDs = !String.IsNullOrWhiteSpace(attributeIDs) 
                    ? attributeIDs.Split(',').Select(x => x.ParseAs<Int32>()) 
                    : null,
                FlagMask = flagMask,
                CreatedFrom = !String.IsNullOrWhiteSpace(createdFrom) 
                    ? Svc.DateTime(createdFrom) 
                    : (DateTime?)null,
                CreatedTo = !String.IsNullOrWhiteSpace(createdTo) 
                    ? Svc.DateTime(createdTo) 
                    : (DateTime?)null,
                PublishedFrom = !String.IsNullOrWhiteSpace(publishedFrom) 
                    ? Svc.DateTime(publishedFrom) 
                    : (DateTime?)null,
                PublishedTo = !String.IsNullOrWhiteSpace(publishedTo) 
                    ? Svc.DateTime(publishedTo) 
                    : (DateTime?)null,
                Index = page * rows,
                Count = rows,
                SortBy = new[] 
                {
                    sidx
                },
                SortDir = sord
            }, new
            {
                DisclosureLevel = "Base",
                DisclosureOptions = new Dictionary<String, String>
                {
                    { "TranslatedTo", JDM.String(Svc.Localization.Language.Code) }
                }.Unload()
            });
            var data = new List<Object>();

            foreach(var i in m.Items)
            {
                var t_pub = (i.Translations as IEnumerable<dynamic>)
                    .SingleOrDefault(x => JDM.Int32(x.Language.EntityID) ==
                        JDM.Int32(Svc.Localization.Language.EntityID));
                data.Add(new[] { 
                    JDM.Int32(i.EntityID),
                    JDM.String(i.Code),
                    t_pub != null ? JDM.String(t_pub.Title) : String.Empty,
                    JDM.Int32(i.CommentCount),
                    JDM.Int32(i.RatingCount),
                    JDM.Byte(i.RatingAverage),
                    Svc.DateTime((DateTime)JDM.DateTime(i.CreatedOn)),
                    Svc.DateTime((DateTime)JDM.DateTime(i.PublishedOn))
                });
            }

            return Json(new
            {
                pageIndex = page + 1,
                pageCount = Math.Ceiling(JDM.Double(m.TotalCount) / rows),
                totalCount = JDM.Int64(m.TotalCount),
                data = data.ToArray()
            });
        }

        #endregion

        #region Child Actions

        [ChildActionOnly]
        public ActionResult _Ratings(int publicationID)
        {
            dynamic m = new ExpandoObject();

            m.EntityID = publicationID;
            m.Ratings = Svc.ProcessOperation("SearchPublicationRatings", new
            {
                HolderID = publicationID
            }, new
            {
                DisclosureLevel = "Extended"
            }).Items;

            return PartialView(m);
        }

        [ChildActionOnly]
        public ActionResult _Comments(int publicationID)
        {
            dynamic m = new ExpandoObject();

            m.EntityID = publicationID;
            m.Comments = Svc.ProcessOperation("SearchPublicationComments", new
            {
                HolderID = publicationID
            }, new
            {
                DisclosureLevel = "Extended"
            }).Items;

            return PartialView(m);
        }

        #endregion
    }
}

